﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace WarOfDev.Core.ExceptionHandling.Attributes
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class ViewHandleErrorAttribute : BaseHandleErrorAttribute
    {
        public ViewHandleErrorAttribute()
        {
            this.IsPartial = true;
        }

        public bool IsPartial { get; set; }


        /// <summary>
        /// Handles session timeout exceptions.
        /// </summary>
        /// <param name="context">The exception context information.</param>
        protected override void HandleSessionExpiredException(ExceptionContext context)
        {
            this.HandleExceptionCore(context, "LoginErrorPartial", "LoginError");
        }

        /// <summary>
        /// Handles authorization exceptions.
        /// </summary>
        /// <param name="context">The exception context information.</param>
        protected override void HandleAuthorizationException(ExceptionContext context)
        {
            this.HandleExceptionCore(context, "NoRightsErrorPartial", "NoRightsError");
        }

        /// <summary>
        /// Handles all frontend exceptions.
        /// </summary>
        /// <param name="context">The exception context information.</param>
        protected override void HandleFrontendException(ExceptionContext context)
        {
            this.HandleExceptionCore(context, "GenericErrorPartial", "GenericError");
        }

        /// <summary>
        /// All handlers handle exception via the method.
        /// </summary>
        /// <param name="context">The exception context information.</param>
        /// <param name="defaultPartialViewName">Default partial view name.</param>
        /// <param name="defaultViewName">Non partial view name.</param>
        private void HandleExceptionCore(ExceptionContext context, string defaultPartialViewName, string defaultViewName)
        {
            // Gets client requested  controller and action
            var controllerName = (string)context.RouteData.Values["controller"];
            var actionName = (string)context.RouteData.Values["action"];

            // Creates view data of the error page or view
            var viewData = new ViewDataDictionary<HandleErrorInfo>()
            {
                Model = new HandleErrorInfo(context.Exception, controllerName, actionName)
            };

            viewData.Add("ErrorMessage", GetDisplayText(context.Exception));

            // Gets error view
            if (string.IsNullOrWhiteSpace(this.View) || string.Compare(this.View, "Error", true) == 0)
            {
                this.View = this.IsPartial ? defaultPartialViewName : defaultViewName;
            }

            // Creates response result
            context.Result = new ViewResult
            {
                ViewName = this.View,               
                ViewData = viewData,
                TempData = context.Controller.TempData
            };
           
            // Only partial view should return 500 status code
            if (this.IsPartial)
            {
                context.HttpContext.Response.StatusCode = 500; // HTTP 'Internal Server Error' code
            }

            context.ExceptionHandled = true;
        }
    }
}
